<?php
/**
 * 构建表单类
 * 
 * ============================================================================
 * 版权所有: (c) 2009-2011，<UEShop Inc>，并保留所有权利。
 * 网站地址: http://www.ueshop.cn
 * ----------------------------------------------------------------------------
 * 这不是一个自由软件！您只能在不用于商业目的的前提下对程序代码进行修改和使用；
 * 不允许对程序代码以任何形式任何目的的再发布。
 * ============================================================================
 *
 * @author      cmpan
 * @copyright   Copyright (c) 2009-2011 UEShop Inc. (http://www.ueshop.cn)
 * @license     http://www.ueshop.cn/1_0.txt
 */
require_once dirname(__FILE__) . '/Object.php';
class UE_Form extends UE_Object {
	/**
	 * 是否用ajax提交
	 *
	 * @var bool
	 */
	protected $_isAjaxPost = false;
	
	/**
	 * 发送请求到的url
	 *
	 * @var string
	 */
	protected $_action = '';
	
	/**
	 * 打开目标窗口: _blank|_self|_parent|_top|自定义
	 *
	 * @var string
	 */
	protected $_target = '_self';
	
	/**
	 * 请求方式 get|post
	 *
	 * @var string
	 */
	protected $_method = 'post';
	
	/**
	 * 请求表单的id
	 *
	 * @var string
	 */
	protected $_id = 'ue_form';
	
	/**
	 * 表单编码方式: application/x-www-form-urlencoded | multipart/form-data
	 *
	 * @var string
	 */
	protected $_enctype = 'application/x-www-form-urlencoded';
	
	/**
	 * 输入元素html
	 *
	 * @var array
	 */
	protected $_elements = array();
	
	/**
	 * 输入元素属性
	 *
	 * @var array
	 */
	protected $_fields = array();
	
	/**
	 * <form ... 这里添加的内容> 
	 *
	 * @var string
	 */
	protected $_append = '';
	
	/**
	 * 是否返回 <form ...></form>标签
	 *
	 * @var bool
	 */
	protected $_hasFormTag = true;
	
    /**#@+
     * 编码方式常量
     */
    const ENCTYPE_URLENCODED = 'application/x-www-form-urlencoded';
    const ENCTYPE_MULTIPART  = 'multipart/form-data';
    /**#@-*/
	
	public function __construct($elements = array()) {
		$elements && $this->addElements($elements);
	}
	
	/**
	 * 添加表单项
	 * 
	 * 格式 $element = array(
	 *   'type' => 'text|textarea',  // 表单类型
	 *   'name' => '',
	 *   'value' => '文本域值',
	 *   'class' => '类a,类b',
	 *   'size' => '长度',
	 *   'maxlength' => '最多允许输入字数',
	 *   'append' => '<input ... 加在这里的内容 />'
	 *   'desc' => '介绍',
	 *   'required' => '0|1', // 是否必填
	 * )
	 *
	 * @param array $element
	 */
	public function addElement($element = array()) {
		if (empty($element['type']) || empty($element['name'])) {
			$this->setErr(var_export($element, true).' have no "type" or "name" Element');
		}
		
		if (strtolower($element['type']) != 'hidden' && !isset($element['title'])) {
			$this->setErr(var_export($element, true).' have no "title" Element');
		}
		
		if (!empty($element['values'])) {
			$element['values'] = trim($element['values']);
			$values = explode("\n", $element['values']);
			$element['values'] = array();
			foreach ($values as $value) {
				$_temp = explode("=", $value);
				isset($_temp[1]) || $_temp[1] = $_temp[0];
				$element['values'][] = array('name' => trim($_temp[1]), 'value' => trim($_temp[0]));
			}			
		}
		
		$this->_fields[$element['name']] = $element;
		if (in_array($element['type'], array('text', 'hidden', 'textarea', 'checkbox', 'radio', 'select', 'file', 'custom', 'date'))) {
			$toDo = '_'.$element['type'];
			$this->$toDo($element);
		}
	}
	
	public function addElements($elements = array()) {
		foreach ($elements as $element) {
			$this->addElement($element);
		}
	}
	
	/**
	 * 文本域
	 * 
	 * 格式 $element = array(
	 *   'type' => 'text',  // 表单类型
	 *   'name' => '',
	 *   'title' => '标题',
	 *   'value' => '文本域值',
	 *   'size' => '长度',
	 *   'maxlength' => '最多允许输入字数',
	 *   'append' => '<input ... 加在这里的内容 />'
	 *   'desc' => '介绍',
	 *   'required' => '0|1', // 是否必填
	 * )
	 *
	 * @param array $element
	 */
	protected function _text($element = array()) {
		$html = '<input type="text" name="'.$element['name'].'" id="'.$element['name'].'"';
		empty($element['value'])      || $html .= ' value="'. htmlspecialchars($element['value']).'"';
		empty($element['size'])       || $html .= ' size="'.(int)$element['size'].'"';
		empty($element['maxlength'])  || $html .= ' maxlength="'.(int)$element['maxlength'].'"';
		empty($element['append'])     || $html .= ' '.$element['append'];
		$html .= ' class="form-text ' . (empty($element['class']) ? '' : $element['class']) . '"';
		$html .= ' />';
		$this->_elements[$element['name']] = $html;
		unset($html);
	}
	
	/**
	 * 隐藏域
	 * 
	 * 格式 $element = array(
	 *   'type' => 'hidden',  // 表单类型
	 *   'name' => '隐藏域',
	 *   'value' => '隐藏域值',
	 * )
	 *
	 * @param array $element
	 */
	protected function _hidden($element = array()) {
		$html = '<input type="hidden" name="'.$element['name'].'" id="'.$element['name'].'"';
		empty($element['value']) || $html .= ' value="'. htmlspecialchars($element['value']).'"';
		$html .= ' />';
		$this->_elements[$element['name']] = $html;
	}
	
	/**
	 * 文件域
	 * 
	 * <input name="x" type="file" size="22" maxlength="55" id="x">
	 * 格式 $element = array(
	 *   'type' => 'file',  // 表单类型
	 *   'name' => '',
	 *   'title' => '标题',
	 *   'size' => '长度',
	 *   'maxlength' => '最多允许输入字数',
	 *   'append' => '<input ... 加在这里的内容 />'
	 *   'desc' => '介绍',
	 *   'required' => '0|1', // 是否必填
	 * )
	 * 
	 * @todo 显示缩略图
	 * @param array $element
	 */
	protected function _file($element = array()) {
		$html = '<input type="file" name="'.$element['name'].'" id="'.$element['name'].'"';
		empty($element['size'])       || $html .= ' size="'. (int)$element['size'].'"';
		empty($element['maxlength'])  || $html .= ' maxlength="'. (int)$element['maxlength'].'"';
		empty($element['append'])     || $html .= ' '.$element['append'];
		$html .= ' class="form-file ' . (empty($element['class']) ? '' : $element['class']) . '"';
		$html .= ' />';
		$this->_elements[$element['name']] = $html;
	}
	
	/**
	 * 自定义表单项
	 *
	 * @param string $element
	 * 
	 * @return UE_Form
	 */	
	protected function _custom($element = array()) {
		$this->_elements[$element['name']] = $element['value'];
		return $this;
	}
	
	/**
	 * 复选框
	 *	 
	 * 格式 $element = array(
	 *   'type' => 'checkbox',  // 表单类型
	 *   'name' => '复选框名称', //必须
	 *   'value' => '默认值|已选中的值', // 系列号后的对象
	 *   'values' => '可选值' //必须
	 *   'title' => '标题', //必须
	 *   'append' => '在最后一个 checkbox 标签加入字的符串'
	 *   'desc' => '介绍',
	 *   'required' => '0|1', // 是否必填
	 * )
	 *
	 * @param array $element
	 */
	protected function _checkbox($element = array()) {
		if (empty($element['values'])) {
			$this->setErr(var_export($element, true).' should have "values" Element');
		}
		
		if(empty($element['value'])) {
			$element['value'] = array();
		} else {
			$element['value'] = unserialize($element['value']);
		}
		
		$html = '';
		foreach ($element['values'] as $key => $checkbox) {
			// $checkbox = array(array('name'=>'', 'value'=>'', 'checked'=>''),...);
			$html .= '<input type="checkbox" name="'.$element['name'].'[]" id="'.$element['name'].'_'.$key.'"';
						
			empty($checkbox['value'])    || $html .= ' value="'. htmlspecialchars($checkbox['value']).'"';
			
			in_array($checkbox['value'], $element['value'])  && $html .= ' checked="checked"';
			
			if (!empty($element['append']) && $key == count($element['values']) - 1) {
				$html .= $element['append'];
			}
			
			$html .= ' class="form-checkbox ' . (empty($element['class']) ? '' : $element['class']) . '"';
			$html .= ' />' . $checkbox['name'] .' ';			
		}
		
		$this->_elements[$element['name']] = $html;
	}
	
	/**
	 * 单选框
	 * 
	 * 格式 $element = array(
	 *   'type' => 'radio',  // 表单类型
	 *   'name' => '', //必须
	 *   'value' => '默认值',
	 *   'values' => '可选值' //必须
	 *   'title' => '标题', //必须
	 *   'append' => '在最后一个 radio标签加入字符串'
	 *   'desc' => '介绍',
	 *   'required' => '0|1', // 是否必填
	 * )
	 *
	 * @param array $element
	 */
	protected function _radio($element = array()) {
		if (empty($element['values'])) {
			$this->setErr(var_export($element, true).' should have "values" Element');
			return false;
		}
		
		//$count = 0;
		$html = ''; //$html = '<span id="'.$element['name'].'">';
		foreach ($element['values'] as $key => $radio) {
			// $radio = array(array('name'=>'', 'value'=>'', 'checked'=>''),...);
			$html .= '&nbsp; <input type="radio" name="'.$element['name'].'" id="'.$element['name'].'_'.$key.'"';
			//$count ++;
			empty($radio['name'])    || $html .= ' value="'. htmlspecialchars($radio['value']).'"';
			
			if(isset($element['value']) && $radio['value'] == $element['value']) {
				$html .= ' checked="checked"';
			}
			
			if (!empty($element['append']) && $key == count($element['values']) - 1) {
				$html .= $element['append'];
			}
			
			$html .= ' class="form-radio ' . (empty($element['class']) ? '' : $element['class']) . '"';
			$html .= ' />'. $radio['name'];
		}
		//$html .='</span>';
		$this->_elements[$element['name']] = $html;
	}
	
	/**
	 * 下拉菜单
	 *
	 * 格式 $element = array(
	 *   'type' => 'select',  // 表单类型
	 *   'name' => '', //必须
	 *   'value' => '默认值',
	 *   'values' => '可选值' //必须
	 *   'title' => '标题', //必须
	 *   'append' => 'select标签中入字符串'
	 *   'desc' => '介绍',
	 *   'required' => '0|1', // 是否必填
	 * )
	 * 
	 * @param array $element
	 */
	protected function _select($element = array()) {
		if (empty($element['values'])) {
			$this->setErr(var_export($element, true).' should have "values" Element');
			return false;
		}
		
		$html = '<select name="'.$element['name'].'" id="'.$element['name'].'"';
		isset($element['multiple'])  && $html .= ' multiple';
		isset($element['size'])      && $html .= ' size="'.$element['size'].'"';
		empty($element['append'])    || $html .= ' '.$element['append'];
		$html .= ' class="form-select ' . (empty($element['class']) ? '' : $element['class']) . '"';
		$html .= '>';
		foreach ($element['values'] as $select) {			
			$html .= '<option value="'. htmlspecialchars($select['value']).'"';
			if (isset($element['value']) && $select['value'] == $element['value']) {
			  	$html .= ' selected="selected"';
			}
			$html .= '>'.$select['name'].'</option>';
		}
		$html .='</select>';
		$this->_elements[$element['name']] = $html;
	}

	/**
	 * 文本区域
	 * 
	 * 格式 $element = array(
	 *   'type' => 'textarea',  // 表单类型
	 *   'name' => '',
	 *   'title' => '标题',
	 *   'value' => '文本域值',
	 *   'size' => '长度',
	 *   'maxlength' => '最多允许输入字数',
	 *   'append' => '<input ... 加在这里的内容 />'
	 *   'cols' => '列数',
	 *   'rows' => '行数', // 
	 *   'disabled' => '是否使文本域不可填',
	 *   'readonly' => '0|1', //是否只读
	 *   'desc' => '介绍',
	 *   'required' => '0|1', // 是否必填
	 * )
	 *
	 * @param array $element
	 */
	protected function _textarea($element = array()) {		
		$html = '<textarea name="'.$element['name'].'" id="'.$element['name'].'"';
		empty($element['cols'])      || $html .= ' cols="'. (int)$element['cols'].'"';
		empty($element['rows'])      || $html .= ' rows="'. (int)$element['rows'].'"';
		isset($element['disabled'])  && $html .= ' disabled';
		isset($element['readonly'])  && $html .= ' readonly="readonly"';
		empty($element['append'])    || $html .= ' '.$element['append'];
		$html .= ' class="form-textarea ' . (empty($element['class']) ? '' : $element['class']) . '"';
		$html .= ' >';		
		empty($element['value'])     || $html .= $element['value'];
		$html .= '</textarea>';
		$this->_elements[$element['name']] = $html;
	}
	
	protected function _date($element = array()) {
		$element['append'] = 'class="datepicker"';
		$this->_text($element);
	}

	/**
	 * 构建图片表单项目
	 *
	 * @param array $element
	 */
	protected function _image($element = array()) {		
		$this->_elements[$element['name']] = $html;
	}
	
	/**
	 * 获取表单html
	 *
	 * @param int $cells 返回2行或是3行
	 * @return string
	 */
	public function getHtml($cells = 3) {
		$form = '';
		$this->_hasFormTag &&
		$form = '<form '
		       .'method="'  .$this->_method    .'" '
		       .'enctype="' .$this->_enctype   .'" '
		       .'action="'  .$this->_action    .'" '
		       .'target="'  .$this->_target    .'" '
		       .'id="'      .$this->_id        .'" ' .$this->_append    .' onsubmit="return Validator.Validate(this)">'."\n";

		// 先获取隐藏域
		foreach ($this->_elements as $key => $element) {
			if ($this->_fields[$key]['type'] == 'hidden') {
				$form .= "$element\n";
				continue;
			}
		}
		
		$form .= '<table width="100%" border="0" cellspacing="0" cellpadding="0" class="rank">'."\n";
		foreach ($this->_elements as $key => $element) {
			if ($this->_fields[$key]['type'] == 'hidden') {
				continue;
			}
			$desc = empty($this->_fields[$key]['desc']) ? '&nbsp;' : $this->_fields[$key]['desc'];
			if(!empty($this->_fields[$key]['required'])) {
				$desc = '(<font color="#FF0000">*</font>)' . $desc;
			}
						
			if($cells == 2) {
				$form .= '  <tr>'."\n"
			            .'    <th class="ui-form-left" width="150" align="right" valign="top">'.$this->_fields[$key]['title'].'</th>'."\n"
			            .'    <td class="ui-form-right" align="left" valign="top">'.$element . ' <div class="note">' .$desc. '</div></td>'."\n"
			            .'  </tr>'."\n";
			} else {
			    $form .= '  <tr>'."\n"
			            .'    <th class="ui-form-left" width="150" align="right" valign="top">'.$this->_fields[$key]['title'].'</th>'."\n"
			            .'    <td class="ui-form-center"  width="320" align="left" valign="top">'.$element . '</td>'."\n"
			            .'    <td class="ui-form-right note" align="left" valign="middle">'.$desc.'</td>'."\n"
			            .'  </tr>'."\n";
			}
		}
		
		$submitTdFix = $cells == 2 ? '' : '    <td class="ui-form-right">&nbsp;</td>'."\n";
		$this->_hasFormTag && 
		            $form  .= '  <tr>'."\n"
		                     .'    <td class="ui-form-left">&nbsp;</td>'."\n"
		                     .'    <td class="ui-form-center">'."\n"
		                     .'      <input type="submit" id="submit_btn" value="提交" class="btn">'."\n"
		                     .'      <input type="reset" id="reset_btn" value="重置" class="btn">'."\n"
		                     .'    </td>'."\n"
		                     .     $submitTdFix
		                     .'  </tr>'."\n";
		$form .= '</table>'."\n";
		
	    $this->_hasFormTag && $form .= '</form>'."\n";
	    
	    return $form;
	}
	
	public function setAction($action = '') {
		$this->_action = $action;
		return $this;
	}
	
	public function setEnctype($enctype = 'application/x-www-form-urlencoded') {
		$this->_enctype = $enctype;
		return $this;
	}
	
	/**
	 * 
	 *
	 * @param string $id
	 * @return UE_Form
	 */
	public function setId($id) {
		$this->_id = $id;
		return $this;
	}
	
	/**
	 * 
	 * @param string $method
	 * @return UE_Form
	 */
	public function setMethod($method = 'post') {
		$this->_method = $method;
		return $this;
	}
	
	/**
	 * @param string $target
	 * @return UE_Form
	 */
	public function setTarget($target = '_self') {
		$this->_target = $target;
		return $this;
	}
	
	/**
	 * 设置<form ... 这里添加的内容> 
	 *
	 * @param string $append
	 * @return UE_Form
	 */
	public function setAppend($append = '') {
		$this->_append = $append;
		return $this;
	}
	
	/**
	 * 设置是否返回form标签
	 *
	 * @param bool $has
	 * @return UE_Form
	 */
	public function setHasFormTag($has = true) {
		$this->_hasFormTag = $has;
		return $this;
	}
}

